package com.hyper_yang._05_juc.chap06;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

//Runnable接口声明使用：
class MyRunnableThread implements Runnable{
    @Override
    public void run() { //缺陷：无返回值，不能声明异常
        System.out.println(Thread.currentThread().getName() + "\t" + " run ---come in");
    }
}

//Callable接口声明使用:
class MyCallableThread implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {  //增强Runnable  run()方法：具有返回值，以及可以声明异常。
        System.out.println(Thread.currentThread().getName() + "\t" + " call---come in");
        Thread.sleep(3000);
        //int i = 1/0;
        return 1000000000;
    }
}

// FutureTask 是连接异步任务执行和同步结果获取的桥梁，解决了 “如何在一个线程中获取另一个线程的执行结果” 的问题
public class CallableDemo {
    public static void main(String[] args) {
        // 创建多线程
//        MyRunnableThread runnableThread = new MyRunnableThread();
//        new Thread(runnableThread, "AA").start();
//        new Thread(runnableThread, "BB").start();

        MyCallableThread myCallableThread = new MyCallableThread();
        FutureTask<Integer> futureTask = new FutureTask<>(myCallableThread); //实现了Runnable接口
        //FutureTask<Integer> futureTask2 = new FutureTask<>(myCallableThread); //实现了Runnable接口
        new Thread(futureTask).start();
        //new Thread(futureTask2).start(); //通过FutureTask启动线程，每一个线程需要创建一个FutureTask

        try {

            Thread.sleep(1000);
//            boolean isCancel = futureTask.cancel(true); //线程正在执行时被取消，再获取get结果就会抛java.util.concurrent.CancellationException异常。
//            if(isCancel){
//                System.out.println("isCancel = true");
//            }else{
//                System.out.println("isCancel = false");
//            }

//            futureTask.cancel(true);
//            boolean cancelled = futureTask.isCancelled();
//            System.out.println("cancelled " + cancelled);

            //等待任务执行完毕
            while (!futureTask.isDone()) { //也可以使用task.isDone()判断子线程是否执行完毕
                Thread.sleep(100);
                System.out.println("wait...");
            }

            System.out.println("main--get前-come in"); //主任务执行与子任务无关情况，将代码放置在get之前，可以并行执行，提高效率。

            Integer result = futureTask.get(); //具有阻塞特点,可以获取线程执行结果。也可以(线程异常抛给FutureTask,FutureTask的get方法调用会再次抛出)捕获异常。
            System.out.println("result = " + result);

            Integer result2 = futureTask.get(); //多次调用get方法，返回都是同一个结果。线程执行只执行一次，将结果保存给FutureTask对象。
            System.out.println("result2 = " + result);

            System.out.println("main--get后-come in"); //主任务执行需要用到子任务的结果，可以放置在get方法后。

        } catch (InterruptedException e) { //阻塞打扰异常。
            System.out.println("出现了InterruptedException = "+ e.getMessage());
            //throw new RuntimeException(e);
        } catch (ExecutionException e) { //线程异常
            System.out.println("出现了ExecutionException = "+ e.getMessage());
            //throw new RuntimeException(e);
        }
    }
}